`timescale 1ns/1ps
`default_nettype none

`define GetPwmBits(lsb, num) I_cfg_pwm_setting[lsb+num-1:lsb]

module pixel_display_mbi6334
    #(
    parameter   DW      = 1
    )
    (
    // system signal
    input  wire         I_sclk,  // 125M
    input  wire         I_rst_n,
    // control
    input  wire         I_enable,
    input  wire         I_frame_sync,
    input  wire         I_enable_5353b,
    
    input  wire         I_ext_lock_output,
    input  wire         I_ext_black_screen,
    
    // config
    input  wire [7:0]   I_cfg_clock_low,     // 时钟低电平时钟数
    input  wire [7:0]   I_cfg_clock_cycle,   // 时钟整周期时钟数
    input  wire [7:0]   I_cfg_clock_phase,   // 时钟相位

    input  wire [5:0]   I_cfg_scan_max       ,
    input  wire [5:0]   I_cfg_port_max       ,

    input  wire [511:0] I_cfg_pwm_setting,   // pwm芯片设置
    // frame id
    output wire         O_frame_req,
    input  wire [1:0]   I_frame_id ,
    
    // display control
    input  wire         I_display_reset,       // 强制重新开始串移
    output wire         O_display_ready,       // 输出模块ready
    output wire         O_display_end,

    input  wire [7:0]   I_display_gclk_low   , // gclk低电平时钟数
    input  wire [7:0]   I_display_gclk_cycle , // gclk整周期时钟数
    input  wire [19:0]  I_display_gclk_extra ,
    
    // read data request
    output reg          O_read_req,        // 读请求
    input  wire         I_read_busy,       // 读忙碌
    output wire [1:0]   O_read_buf_sel,
    
    output wire [5:0]   O_read_scan_id,
    output wire [5:0]   O_read_scan_max,
    
    output wire [5:0]   O_read_port_max,
    
    output wire [5:0]   O_read_pin_id,
    output wire [5:0]   O_read_pin_max,
    
    output reg  [5:0]   O_read_chip_id,         // 读第几个芯片
    output reg  [5:0]   O_read_chip_max,         
    
    output reg  [8:0]   O_read_ram_addr,
    output reg          O_read_buf_index,
    
    
    // display buf 显示数据 64x8x16bit x 2
    output reg          O_ram_rden,
    output reg  [13:0]  O_ram_raddr,
    output reg          O_ram_raddr_sel,
    input  wire [DW-1:0]I_ram_rdata,
    
    // dot data request
    output reg          O_read_dot_req,        // 读请求
    input  wire         I_read_dot_busy,       // 读忙碌
    output reg  [3:0]   O_read_dot_id,         // 读第几个芯片
    //  Dot correction code  校正数据64x8x8bit x 2
    output wire         O_dotcor_rden,
    output reg  [11:0]  O_dotcor_raddr,
    input  wire         I_dotcor_rdata,


    //cfg_buf 16x16bit寄存器
    output wire         O_cfg_rden,
    output reg  [7:0]   O_cfg_raddr,
    input  wire         I_cfg_rdata,
    

 // dot data request
    output reg          O_read_mask_req,        // 读请求
    input  wire         I_read_mask_busy,       // 读忙碌
    output reg  [3:0]   O_read_mask_id,         // 读第几个芯片
    //mask_buf 4x16bit寄存器
    output wire         O_mask_rden,
    output reg  [1:0]   O_mask_raddr,
    input  wire         I_mask_rdata,

    // led signal
    output wire         O_oe_out,
    output wire         O_load_out,
    output wire         O_clock_out,
    output wire [DW-1:0]O_data_out,
    output wire         O_vsync,

    input  wire         set_clk,
    input  wire [7:0]   set_data ,
    input  wire         set_d_ok,
    input  wire [23:0]  set_addr,
    output wire [15:0]  tout
);


//------------------------Parameter----------------------
// delay
localparam  L = 3;  // 读ram延时=4

// fsm
localparam [4:0]
        IDLE            =  0,
        VSYNC0          =  1,
        CS_START_DELAY  =  2,
        PACK_HEAD_REQ   =  3,
        PACK_HEAD_DATA  =  4,
        DATA_REQ        =  5,
        DATA            =  6,
        DATA_LOOP       =  7,
        DUMMY_REQ       =  8,
        DUMMY_DATA      =  9,
        READ_NEXT       =  10,
        NOP0            =  11,
        NOP1            =  12,
        NOP2            =  13,
        LOOP            =  14,
        FRAME_END_DELAY =  15,
        FRAME_END_REQ   =  16,
        FRAME_END_DATA  =  17,
        FRAME_END_DELAY1=  18,
        VSYNC_DELAY     =  19,
        VSYNC_DELAY1    =  20,
        WAIT            =  21;

//------------------------Local signal-------------------
// fsm
reg  [4:0]  state/* synthesis syn_keep=1 */;
reg  [4:0]  next;

// pwm setting
wire [5:0]  cfg_chip_num;      // 串移链中芯片数量
wire [15:0] cfg_port0_reg1;    // port0寄存器1的值
wire [15:0] cfg_port0_reg2;    // port0寄存器2的值
wire [15:0] cfg_port0_reg3;    // port0寄存器3的值
wire [15:0] cfg_port0_reg4;    // port0寄存器4的值
wire [15:0] cfg_port0_reg5;    
wire [15:0] cfg_port0_reg6;    
wire [15:0] cfg_port0_reg7;    
wire [15:0] cfg_port0_reg8;    
wire [15:0] cfg_port0_reg9;    
wire [15:0] cfg_port0_reg10;    
wire [15:0] cfg_port0_reg11;   
wire [15:0] cfg_port0_reg12;   
wire [15:0] cfg_port0_reg13;   
wire [15:0] cfg_port0_reg14;   
wire [15:0] cfg_port0_reg15;   
wire [15:0] cfg_port0_reg16;   
// wire        cfg_init_gclk;

// shift request
reg         shift_req;       // 串移开始
wire        shift_busy;      // 正在串移
reg  [14:0] shift_bit_num;   // 串移长度(bit)

reg  [DW-1:0] shift_data;      // 串移数据
wire        shift_data_ack;  // 数据确认
reg  [15:0] port0_reg;
reg         shift_over;



// led signal
wire        oe_out;
wire        load_out;
wire        clock_out;
wire [DW-1:0] data_out;

// misc
reg         display_ready;

reg         mbi6334_cs;

reg  [63:0] pack_data;
reg  [9:0]  delay_cnt;

reg  [2:0]  read_cnt; // 0:读寄存器 1：读校正 2：显示数据 3:mask 4：结束码

reg         data_end; //所有芯片一次数据完成

reg  [5:0]  read_chip_id;         // 读第几个芯片

reg  [15:0] checksum; //校验和
//------------------------Instantiation------------------
// data_shift
data_shift_mbi6334 /*{{{*/
    #(
    .DW                (DW      )
    )
  ds (
    .I_sclk            ( I_sclk ),
    .I_rst_n           ( I_rst_n ),
    .I_cfg_clock_low   ( I_cfg_clock_low ),
    .I_cfg_clock_cycle ( I_cfg_clock_cycle ),
    .I_cfg_clock_phase ( I_cfg_clock_phase ),
    
    .I_shift_req       ( shift_req ),
    .O_shift_busy      ( shift_busy ),
    .I_shift_bit_num   ( shift_bit_num ),

    .I_shift_data      ( shift_data ),
    .O_shift_data_ack  ( shift_data_ack ),

    .O_clock_out       ( clock_out ),
    .O_data_out        ( data_out )
);
gclk_gen_mbi6334 gs(
    // system signal
    .I_sclk             ( I_sclk ),// 125M
    .I_rst_n            ( I_rst_n ),
    
    .I_cfg_gclk_low     ( I_display_gclk_low ),// 时钟低电平时钟数
    .I_cfg_gclk_cycle   ( I_display_gclk_cycle ),// 时钟整周期时钟数
    
    .O_gclk_out         ( oe_out )
);
//------------------------Body---------------------------
//{{{+++++++++++++++++++++fsm++++++++++++++++++++++++++++
// state
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        state <= IDLE;
    else if (!I_enable )
        state <= IDLE;
    else
        state <= next;
end

// next
always @(*) begin
    case (state)
        IDLE: begin
            if (I_frame_sync)
                next = VSYNC0;
            else 
                next = IDLE;
        end

        VSYNC0: begin
            next = CS_START_DELAY;
        end
        
        CS_START_DELAY:begin    //cs 开始等待一段时间开始时钟
            if (delay_cnt == 'd0)
                next = PACK_HEAD_REQ;
            else 
                next = CS_START_DELAY;
        end

        PACK_HEAD_REQ:begin
            next = PACK_HEAD_DATA;
        end
        
        PACK_HEAD_DATA: begin     
            if (shift_req || shift_busy)
                next = PACK_HEAD_DATA;
            else
                next = DATA_REQ;
        end
        
        DATA_REQ: begin     
           next = DATA;
        end
        
        DATA: begin
            if (shift_req || shift_busy)
                next = DATA;
            else 
                next = DATA_LOOP;
        end
        
        DATA_LOOP:begin
            if(data_end)
                next = DUMMY_REQ;
            else
                next = DATA_REQ;
        
        end
        
        DUMMY_REQ:begin
            next = DUMMY_DATA;
        end

        DUMMY_DATA: begin
            if (shift_req || shift_busy)
                next = DUMMY_DATA;
            else
                next = READ_NEXT;
        end

        READ_NEXT: begin         
            next = NOP0;
        end

        NOP0: begin
            if (delay_cnt == 'd0)  //cs结束与数据的间隔
                next = NOP1;
            else 
                next = NOP0;
        end

        NOP1: begin
            next = NOP2;
        end
        
        NOP2: begin
            if (delay_cnt == 'd0)  //空闲2us
                next = LOOP;
            else 
                next = NOP2;
        end
        
        
        LOOP: begin
            if (shift_over)
                next = FRAME_END_DELAY;
            else
                next = CS_START_DELAY;
        end
        
        FRAME_END_DELAY:begin
            if(delay_cnt == 0)
                next = FRAME_END_REQ;
            else 
                next = FRAME_END_DELAY;
        end

        FRAME_END_REQ:begin
            next = FRAME_END_DATA;
        end
        
        FRAME_END_DATA: begin    
            if (shift_req || shift_busy)
                next = FRAME_END_DATA;
            else 
                next = FRAME_END_DELAY1;
        end
        
        FRAME_END_DELAY1:begin
            if(delay_cnt == 0)
                next = VSYNC_DELAY;
            else 
                next = FRAME_END_DELAY1;
        
        end
        
        VSYNC_DELAY:begin
            if(delay_cnt == 0)
                next = VSYNC_DELAY1;
            else 
                next = VSYNC_DELAY;
        
        end
        
        VSYNC_DELAY1:begin
            if(delay_cnt == 0)
                next = WAIT;
            else 
                next = VSYNC_DELAY1;
        
        end

        WAIT: begin
            if (I_frame_sync)
                next = VSYNC0;
            else
                next = WAIT;
        end

        default: begin
            next = IDLE;
        end
    endcase
end

//cs
always @(*) begin
    case (state)
        CS_START_DELAY  ,
        PACK_HEAD_REQ   ,
        PACK_HEAD_DATA  ,
        DATA_REQ        ,
        DATA            ,
        DATA_LOOP       ,
        DUMMY_REQ       ,
        DUMMY_DATA      ,
        READ_NEXT       ,
        NOP0            ,
        FRAME_END_DELAY ,
        FRAME_END_REQ   ,
        FRAME_END_DATA  ,
        FRAME_END_DELAY1:begin
            mbi6334_cs <= 1'b0;
        end

        default: begin
            mbi6334_cs <= 1'b1;
        end
    endcase
end
// reg [7:0]cfg_raddr;
//cfg reg read
always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)
        O_cfg_raddr <= 1'b0;
    else if( state == VSYNC0)
        O_cfg_raddr <= 1'b0;
    else if (state == DATA && read_cnt == 'd0) begin
        if(shift_data_ack)
            O_cfg_raddr <= O_cfg_raddr + 1'b1;
    end
end

assign O_cfg_rden = 1'b1;


//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++
assign cfg_port0_reg1   =  16'hC3F0;    //16'hc170;     //32组 8扫 
assign cfg_port0_reg2   =  16'h0800;    //16'h0800;     //fdc enable
assign cfg_port0_reg3   =  16'h0018;    //16'h0018;     
assign cfg_port0_reg4   =  16'h0808;    //16'h0808;     [15:8]DM  [7:0]DT
assign cfg_port0_reg5   =  16'hff07;    //16'h3307;     [15:8]global current gain setup 5-30ma [5:3]rising time  [2:0]falling time 
assign cfg_port0_reg6   =  16'hF600;    //16'hF600;     [15:13]de-ghost level
assign cfg_port0_reg7   =  16'h0000;    //16'h0000;     
assign cfg_port0_reg8   =  16'h0000;    //16'h0000;     [15:8] ST ,[7:0]CT
assign cfg_port0_reg9   =  16'he020;    //16'he820;     
assign cfg_port0_reg10  =  16'h0002;    //16'h0002;     
assign cfg_port0_reg11  =  16'h3396;    //16'h3396;     
assign cfg_port0_reg12  =  16'h3033;    //16'h3033;     
assign cfg_port0_reg13  =  16'h7211;    //16'h7211;     //16'h0011;
assign cfg_port0_reg14  =  16'h0001;    //16'h0001;     //16'h0002;
assign cfg_port0_reg15  =  16'h0000;    //16'h0000;     //16'h0000;
assign cfg_port0_reg16  =  16'ha034;    //16'ha034;     //16'h0000;
                            
always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)           
        port0_reg <= 1'b0;
    else if(  state == DATA_REQ && read_cnt == 'd0)
        port0_reg <= cfg_port0_reg1;
    else if (state == DATA && read_cnt == 'd0) begin
        if(shift_data_ack)begin
            if(O_cfg_raddr[3:0] == 'd15)
                case(O_cfg_raddr[7:4])
                    0:  port0_reg <= cfg_port0_reg2;
                    1:  port0_reg <= cfg_port0_reg3;
                    2:  port0_reg <= cfg_port0_reg4;

                    3:  port0_reg <= cfg_port0_reg5;
                    4:  port0_reg <= cfg_port0_reg6;
                    5:  port0_reg <= cfg_port0_reg7;
                    6:  port0_reg <= cfg_port0_reg8;
                                
                    7:  port0_reg <= cfg_port0_reg9;
                    8:  port0_reg <= cfg_port0_reg10;
                    9:  port0_reg <= cfg_port0_reg11;
                    10:  port0_reg <= cfg_port0_reg12;
                    
                    11:  port0_reg <= cfg_port0_reg13;
                    12:  port0_reg <= cfg_port0_reg14;
                    13:  port0_reg <= cfg_port0_reg15;
                    14:  port0_reg <= cfg_port0_reg16;
                    
                    15:  port0_reg <= cfg_port0_reg1;
                endcase
            else
                port0_reg <= {port0_reg[14:0], 1'd0};
        end
        else 
            port0_reg <= port0_reg;
    end
end



assign O_mask_rden = 1'b1;
always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)
        O_mask_raddr <= 1'b0;
    else if( state == VSYNC0)
        O_mask_raddr <= 1'b0;
    else if (state == DATA && read_cnt == 'd3) begin
        if(shift_data_ack)
            O_mask_raddr <= O_mask_raddr + 1'b1;
    end
end


assign cfg_chip_num   =  'd5;


always @(posedge I_sclk or negedge I_rst_n) begin
    if(!I_rst_n)
        read_cnt <= 'd0;
    else if(state == VSYNC0)
        read_cnt <= 'd0;
    else if(state == NOP1)
        read_cnt <= read_cnt + 1'd1;
end


// read_chip_id
always @(posedge I_sclk or negedge I_rst_n) begin
    if(!I_rst_n)
        read_chip_id <= 'd0;
    else if(state ==  VSYNC0)begin
        read_chip_id <= 'd0;
    end
    else if( state == DATA_REQ)begin
        if(read_cnt == 'd2)begin
            if(read_chip_id == cfg_chip_num-1)
                read_chip_id <= 0;
            else 
                read_chip_id <= read_chip_id + 1'b1;
        end
        else begin
            read_chip_id <= 0;
        end
    end
end

always @(posedge I_sclk or negedge I_rst_n) begin
    if(!I_rst_n)
        data_end <= 'd0;
    else if(state == NOP1 && state == VSYNC0)
        data_end <= 'd0;
    else if(state == DATA_REQ)begin
        if(read_cnt == 'd2)begin
            if(read_chip_id == cfg_chip_num-1)
                data_end <=1;
            else 
                data_end <=0;
        end
        else begin
            data_end <= 1;
        end
    end
end

// O_read_dot_req
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        O_read_dot_req <= 1'b0;
    else if (state == VSYNC0)
        O_read_dot_req <= 1'b1;
    else if(state == DATA_REQ)begin
        if(read_cnt == 'd1 && read_chip_id != cfg_chip_num-1)
            O_read_dot_req <= 1'b1;
        else 
            O_read_dot_req <= 1'b0;
        
    end
    else
        O_read_dot_req <= 1'b0;
end

always@(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n)
        O_read_dot_id <= 'd0;
    else if(state == WAIT)
        O_read_dot_id <= 'd0;
    else if(O_read_dot_req)
        O_read_dot_id <= O_read_dot_id + 'd1;
end

assign O_dotcor_rden = 1'b1;
always @(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n)
        O_dotcor_raddr[11:0] <= 'd0;
    else if(read_cnt == 'd1 && state == DATA && shift_data_ack)begin
        O_dotcor_raddr[11:0] <= O_dotcor_raddr[11:0] + 1'b1;
    end
    else if(state == WAIT)
        O_dotcor_raddr[11:0] <= 'd0;
end
// always @(posedge I_sclk )begin
    // if( state == DATA_REQ)
        // O_dotcor_raddr[12] <= read_chip_id[0];
// end

//O_read_req
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        O_read_req <= 1'b0;
    else if(state == DATA_REQ)begin
        if(read_cnt == 'd0 ) //读寄存器时，读显示数据
            O_read_req <= 1'b1;
        else if(read_cnt == 'd2 && read_chip_id != cfg_chip_num-1)
            O_read_req <= 1'b1;
        else 
            O_read_req <= 1'b0;
    end
    else
        O_read_req <= 1'b0;
end

always@(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n)
        O_read_chip_id <= 'd0;
    else if(state == WAIT)
        O_read_chip_id <= 'd0;
    else if(O_read_req)
        O_read_chip_id <= O_read_chip_id + 'd1;
end

always@(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n)
        O_read_buf_index <= 'd0;
    else if(O_read_req)
        O_read_buf_index <= O_read_buf_index + 'd1;
end


// assign O_ram_rden = 1'b1;
// assign O_ram_rden = ((state == DATA_REQ && read_cnt == 'd1) || (read_cnt == 'd2 && state == DATA && shift_data_ack));
always @(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n)
        O_ram_raddr[12:0] <= 'd0;
    // else if(read_cnt == 'd2 && state == DATA && shift_data_ack)begin
    else if(O_ram_rden)begin
        O_ram_raddr[12:0] <= O_ram_raddr[12:0] + 1'b1;
    end
    else if(state == WAIT || state ==IDLE || state ==DATA_REQ)
        O_ram_raddr[12:0] <= 'd0;
end
// always @(posedge I_sclk )begin
    // if( state == DATA_REQ)
        // O_ram_raddr[13] <= read_chip_id[0];
// end

always @(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n)
        O_ram_raddr[13] <= 'd0;
    else if( (state == DATA_REQ && read_cnt == 'd2) )
        O_ram_raddr[13] <= ~O_read_buf_index;
end

always@(posedge I_sclk or negedge I_rst_n)begin
    if(!I_rst_n)
        O_ram_rden <= 'd0;
    else if ( (state == DATA_REQ && read_cnt == 'd2 )  ||  (read_cnt == 'd2 && state == DATA && shift_data_ack))
        O_ram_rden <= 'd1;
    else 
        O_ram_rden <= 'd0;
end

always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)
        shift_req <= 1'b0;
    else
    case(state)
        PACK_HEAD_REQ   ,
        DATA_REQ        ,
        DUMMY_REQ       ,
        FRAME_END_REQ   :
            shift_req <= 1'b1;

        default:    shift_req <= 1'b0;
    endcase
end

// shift_bit_num
always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)
        shift_bit_num <= 1'b0;
    else
    case(state)

        PACK_HEAD_REQ:      shift_bit_num <= {11'd3 ,4'd0};
        DATA_REQ:   begin        
                    case (read_cnt[2:0])
                        0:begin //bc
                            shift_bit_num <= {11'd16 ,4'd0};
                        end
                        1:begin //dc
                            shift_bit_num <= {11'd256 ,4'd0};
                        end
                        3:begin //mask
                            shift_bit_num <= {11'd4 ,4'd0};
                        end
                        default:begin
                            shift_bit_num <= {11'd512 ,4'd0};
                        end
                    
                    endcase
        end
        DUMMY_REQ:          shift_bit_num <= {cfg_chip_num ,4'd0};
        
        FRAME_END_REQ:      shift_bit_num <= { 11'd3 + cfg_chip_num ,4'd0};

        default:            shift_bit_num <= shift_bit_num;
    endcase
end

// shift_data
always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)
        shift_data <= 1'b0;
    else
    case(state)
        PACK_HEAD_DATA:    shift_data <= { pack_data[63]};
        DATA:begin
                if(read_cnt == 0)
                    // shift_data <= I_cfg_rdata;
                    shift_data <= port0_reg[15];
                else if(read_cnt == 1)
                    shift_data <= I_dotcor_rdata;
                else if(read_cnt == 3) //mask
                    shift_data <= I_mask_rdata;
                else
                    shift_data <= I_ram_rdata;
        end
        DUMMY_DATA:         shift_data <= checksum[15];
        FRAME_END_DATA:     shift_data <= { pack_data[63]};
        default : shift_data <= shift_data;
    endcase
end

always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)
        pack_data <= 1'b0;
    else if (state == PACK_HEAD_REQ) begin
        if(read_cnt == 'd0) //寄存器
            pack_data <= { 16'h8000, 16'h0010 , 16'h0000 ,16'h0000 };
        else if(read_cnt== 'd1) //校正数据
            pack_data <= { 16'h8000, 16'h0100 , 16'h0230 ,16'h0000 };
        else if(read_cnt== 'd3) //mask
            pack_data <= { 16'h8000, 16'h0004 , 16'h0400 ,16'h0000 };
        else //显示数据
            pack_data <= { 16'hbf00, 16'h0200 , 16'h0020 ,16'h0000 };
    end
    else if( state ==  FRAME_END_REQ)begin
        pack_data <= { 16'hC000, 16'h001f , 16'h0001 ,16'hffe0 };
    end
    else if (shift_data_ack)
        pack_data <= {pack_data[62:0], 1'd0};
end


always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)
        checksum <= 1'b0;
    else if(state == DUMMY_REQ)begin
        case(read_cnt)
        0: checksum <=16'h9cb4;
        1: checksum <=16'h01d0;
        2: checksum <=16'hf7e0;
        3: checksum <=16'hfbc4;
        endcase
    end
    else if (shift_data_ack)
        checksum <= {checksum[14:0] , 1'd0};

end


always @(posedge I_sclk or negedge I_rst_n) begin
    if(~I_rst_n)
        delay_cnt <= 0;
    else begin 
        case(state )
        VSYNC0: begin
            delay_cnt <=   'd16;
        end
        READ_NEXT: begin        
           delay_cnt <=    'd16; 
        end
        NOP1: begin
            delay_cnt <=   'd250;
        end
        LOOP:begin
            delay_cnt <=   'd16;  //2us
        end
        FRAME_END_DATA:begin
            delay_cnt <=  'd16;
        end
        FRAME_END_DELAY1:begin
            if(delay_cnt == 'd0)
                delay_cnt <= 'd256;
            else 
                delay_cnt <= delay_cnt - 'd1;
        end
        
        VSYNC_DELAY:begin
            if(delay_cnt == 'd0)
                delay_cnt <= 'd256;
            else 
                delay_cnt <= delay_cnt - 'd1;
        end
        
        default: begin
            if(delay_cnt != 'd0)
                delay_cnt <= delay_cnt-1;
        end

        endcase 
    end
end



//{{{+++++++++++++++++++++frame id+++++++++++++++++++++++
assign O_frame_req = (state == VSYNC0);
//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++



// shift_over
always @(posedge I_sclk or negedge I_rst_n) begin
    if (~I_rst_n)
        shift_over <= 1'b0;
    else if (state == VSYNC0)
        shift_over <= 1'b0;
    else if (state == NOP2 && read_cnt == 'd4)
        shift_over <= 1'b1;
end



//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++

//{{{+++++++++++++++++++++led signal+++++++++++++++++++++
assign O_oe_out    = (!I_enable)? 1'b0 : oe_out;
assign O_load_out  = (!I_enable)? 1'b0 : mbi6334_cs;
assign O_clock_out = (!I_enable)? 1'b0 : clock_out;
assign O_data_out  = (!I_enable)? 1'b0 : data_out;
//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++
assign O_vsync = (!I_enable)? 1'b0 : (state == VSYNC_DELAY1);


assign O_read_buf_sel   = I_frame_id    ;
assign O_read_scan_id   = 'd0           ;
assign O_read_scan_max  = I_cfg_scan_max;
assign O_read_port_max  = I_cfg_port_max - 1;
assign O_read_pin_id    = 'd0           ;
assign O_read_pin_max   = 'd63          ;

always@(*)
    O_read_chip_max <= cfg_chip_num - 1;
//{{{+++++++++++++++++++++misc+++++++++++++++++++++++++++
assign O_display_ready = display_ready;
// display_ready
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        display_ready <= 1'b0;
    else if (!I_enable)
        display_ready <= 1'b0;
    else if (state == VSYNC0)
        display_ready <= 1'b1;
end


//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++

endmodule

`default_nettype wire

// vim:set ts=4 sw=4 et fenc=utf-8 fdm=marker:
